import ProFormTree from '@/components/ProFormTree';
import SearchTablePage, { SearchTablePageRefType } from '@/components/SearchTablePage';
import { DATA_SCOPE_TYPE_DESIGNATED_ORG, PERMISSION_KEY_ROLE } from '@/constants';
import { getMenuTree } from '@/services/system/menu';
import { getOrgTrees } from '@/services/system/org';
import {
  addRole,
  addRoleData,
  addRoleMenu,
  deleteRoleById,
  getRoleById,
  getRoleList,
  listRoleMenus,
  updateRole,
} from '@/services/system/role';
import { checkRespSuccessful } from '@/utils/serviceUtils';
import { ModalForm, ProFormInstance, ProFormSelect, ProFormText } from '@ant-design/pro-components';
import { Access, useAccess, useModel } from '@umijs/max';
import { message } from 'antd';
import { Key, useRef, useState } from 'react';

const Role: React.FC = () => {
  const [linkMenuModalOpen, setLinkMenuModalOpen] = useState(false);
  const [linkDataScopModalOpen, setLinkDataScopModalOpen] = useState(false);
  const modalFormRef = useRef<ProFormInstance>();
  const [currentRow, setCurrentRow] = useState<API.Role>();
  const [currentDataScope, setCurrentDataScope] = useState<Key>();
  const searchTablePageActionRef = useRef<SearchTablePageRefType>(null);
  const { initialState } = useModel('@@initialState');
  const access = useAccess();
  return (
    <>
      <SearchTablePage<API.Role>
        tableName="角色"
        ref={searchTablePageActionRef}
        getRowById={getRoleById}
        updateRow={updateRole}
        addRow={addRole}
        deleteRowById={deleteRoleById}
        getRowsByPage={getRoleList}
        rowSelection={false}
        permissionKey={PERMISSION_KEY_ROLE}
        columns={[
          {
            title: '角色 ID',
            dataIndex: 'id',
            hideInTable: true,
            hideInSearch: true,
            hideInModal: true,
          },
          {
            title: '角色名称',
            dataIndex: 'name',
            showDetail: true,
            rules: [{ required: true }],
          },
          {
            title: '角色标识',
            dataIndex: 'code',
            hideInSearch: true,
            rules: [{ required: true }],
          },
          {
            title: '角色状态',
            dataIndex: 'status',
            valueType: 'select',
            valueEnum: initialState?.system_common_status?.valueEnum,
            options: initialState?.system_common_status?.numOptions,
            rules: [{ required: true, message: '请选择状态' }],
          },
          {
            title: '角色类型',
            dataIndex: 'type',
            hideInSearch: true,
            valueType: 'tag',
            valueEnum: initialState?.system_role_type?.tagValueEnum,
            options: initialState?.system_role_type?.options,
            rules: [{ required: true, message: '请选择角色类型' }],
          },
          {
            title: '数据权限范围',
            dataIndex: 'dataScope',
            valueType: 'select',
            hideInSearch: true,
            valueEnum: initialState?.system_data_scope?.valueEnum,
            options: initialState?.system_data_scope?.numOptions,
          },
          {
            title: '机构权限',
            dataIndex: 'dataScopeDeptIds',
            valueType: 'treeSelect',
            hideInSearch: true,
            hideInTable: true,
            allowClear: true,
            secondary: true,
            request: async () => {
              const res = await getOrgTrees();
              if (checkRespSuccessful(res)) {
                return res.data || [];
              }
              return [];
            },
            fieldProps: {
              fieldNames: {
                value: 'id',
              },
              multiple: true,
              treeCheckable: true,
            },
          },
          {
            title: '备注',
            dataIndex: 'remark',
            hideInSearch: true,
            hideInTable: true,
          },
          {
            title: '创建时间',
            dataIndex: 'createTime',
            valueType: 'dateTime',
            hideInSearch: true,
            hideInModal: true,
          },
        ]}
        actionRender={(text, record, nodes) => {
          return [
            <Access
              key="bindMenu"
              accessible={access.permissionFilter(PERMISSION_KEY_ROLE.addRoleMenu)}
            >
              <a
                onClick={() => {
                  setCurrentRow(record);
                  setLinkMenuModalOpen(true);
                }}
                type="link"
                style={{
                  flex: undefined,
                }}
              >
                分配菜单
              </a>
            </Access>,
            <Access
              key="bindScopData"
              accessible={access.permissionFilter(PERMISSION_KEY_ROLE.addRoleData)}
            >
              <a
                onClick={() => {
                  setCurrentRow(record);
                  setLinkDataScopModalOpen(true);
                }}
                type="link"
                style={{
                  flex: undefined,
                }}
              >
                权限范围
              </a>
            </Access>,
            ...nodes,
          ];
        }}
      />
      {linkMenuModalOpen && (
        <ModalForm
          title="分配菜单"
          width={600}
          layout="horizontal"
          labelCol={{ span: 5 }}
          open={linkMenuModalOpen}
          omitNil
          isKeyPressSubmit
          request={async () => {
            if (currentRow && currentRow.id !== undefined) {
              const res = await listRoleMenus(currentRow.id);
              if (checkRespSuccessful(res)) {
                return {
                  roleId: currentRow?.id,
                  name: currentRow?.name,
                  code: currentRow?.code,
                  menuIds: res.data,
                };
              }
            }
            return {
              roleId: currentRow?.id,
              name: currentRow?.name,
              code: currentRow?.code,
            };
          }}
          onOpenChange={setLinkMenuModalOpen}
          onFinish={async (values) => {
            const hide = message.loading(`正在更新菜单权限`);
            try {
              const { roleId, menuIds } = values;

              if (!roleId) {
                message.error(`未选中任何角色，无法分配菜单`);
                return;
              }

              const res = await addRoleMenu({ roleId, menuIds: menuIds || [] });
              hide();
              if (checkRespSuccessful(res)) {
                message.success(`菜单权限分配成功`);
                setLinkMenuModalOpen(false);
                setCurrentRow(undefined);
              } else {
                message.error(`菜单权限分配失败，后台响应：${res.message}，请重试`);
              }
            } catch (error) {
              hide();
              message.error(`菜单权限分配失败，请重试`);
            }
          }}
          formRef={modalFormRef}
        >
          <ProFormText hidden rules={[{ required: true }]} name="roleId" label="角色 ID" />
          <ProFormText readonly name="name" label="角色名称" />
          <ProFormText readonly name="code" label="角色标识" />
          <ProFormTree
            name="menuIds"
            label="关联菜单"
            // showLine
            checkable
            fieldNames={{
              label: 'name',
              value: 'id',
            }}
            request={async () => {
              const res = await getMenuTree();
              if (checkRespSuccessful(res)) {
                return res.data || [];
              }
              return [];
            }}
          />
        </ModalForm>
      )}
      {linkDataScopModalOpen && (
        <ModalForm
          title="分配数据权限范围"
          width={600}
          layout="horizontal"
          labelCol={{ span: 5 }}
          open={linkDataScopModalOpen}
          omitNil
          isKeyPressSubmit
          request={async () => {
            setCurrentDataScope(currentRow?.dataScope);
            return {
              roleId: currentRow?.id,
              name: currentRow?.name,
              code: currentRow?.code,
              dataScope: currentRow?.dataScope,
              dataScopeDeptIds: currentRow?.dataScopeDeptIds || [],
            };
          }}
          onOpenChange={setLinkDataScopModalOpen}
          onFinish={async (values) => {
            const hide = message.loading(`正在更新机构权限`);
            try {
              const { roleId, dataScope, dataScopeDeptIds } = values;

              if (!roleId) {
                message.error(`未选中任何角色，无法分配机构权限`);
                return;
              }

              const res = await addRoleData({
                roleId,
                dataScope,
                dataScopeDeptIds: dataScopeDeptIds || [],
              });
              hide();
              if (checkRespSuccessful(res)) {
                message.success(`机构权限分配成功`);
                setLinkDataScopModalOpen(false);
                setCurrentRow(undefined);
                searchTablePageActionRef.current?.refresh();
              } else {
                message.error(`机构权限分配失败，后台响应：${res.message}，请重试`);
              }
            } catch (error) {
              hide();
              message.error(`机构权限分配失败，请重试`);
            }
          }}
          formRef={modalFormRef}
        >
          <ProFormText hidden rules={[{ required: true }]} name="roleId" label="角色 ID" />
          <ProFormText readonly name="name" label="角色名称" />
          <ProFormText readonly name="code" label="角色标识" />
          <ProFormSelect
            name="dataScope"
            label="数据权限范围"
            allowClear
            secondary
            options={initialState?.system_data_scope?.numOptions}
            fieldProps={{
              onChange: (value) => {
                setCurrentDataScope(value);
              },
            }}
          />
          <ProFormTree
            hidden={currentDataScope !== DATA_SCOPE_TYPE_DESIGNATED_ORG}
            name="dataScopeDeptIds"
            label="指定授权机构"
            // showLine
            checkable
            fieldNames={{
              value: 'id',
            }}
            request={async () => {
              const res = await getOrgTrees();
              if (checkRespSuccessful(res)) {
                return res.data || [];
              }
              return [];
            }}
          />
        </ModalForm>
      )}
    </>
  );
};

export default Role;
